home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / libwww2 / HTFWriter.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  13.3 KB  |  555 lines

  1. /*        FILE WRITER                HTFWrite.h
  2. **        ===========
  3. **
  4. **    This version of the stream object just writes to a C file.
  5. **    The file is assumed open and left open.
  6. **
  7. **    Bugs:
  8. **        strings written must be less than buffer size.
  9. */
  10.  
  11. #include "HTFWriter.h"
  12.  
  13. #include "HTFormat.h"
  14. #include "HTAlert.h"
  15. #include "HTFile.h"
  16. #include "HText.h"
  17. #include "tcp.h"
  18. #include "HTCompressed.h"
  19. #ifdef _AMIGA
  20. #include <string.h>
  21.  
  22. #include <proto/dos.h>
  23. #include <dos/dostags.h>
  24. #endif
  25.  
  26. /*        Stream Object
  27. **        ------------
  28. */
  29.  
  30. struct _HTStream {
  31.     CONST HTStreamClass *    isa;
  32.  
  33.     FILE *            fp;
  34.     char * fnam;
  35.     char *            end_command;
  36.     int compressed;
  37.     int interrupted;
  38.     int write_error;
  39. };
  40.  
  41. /* #define TRACE 1 */
  42.  
  43. /* MOSAIC: We now pick up some external variables, handled
  44.    in src/mo-www.c: */
  45. extern int force_dump_to_file;
  46. extern char *force_dump_filename;
  47. /* If force_dump_to_file is high, we know we want to dump the
  48.    data into a file already named by force_dump_filename and not
  49.    do anything else. */
  50.  
  51. /* If this is high, then we just want to dump the thing to a file;
  52.    the file is named by force_dump_filename. */
  53. extern int binary_transfer;
  54.  
  55. extern void rename_binary_file (char *);
  56.  
  57. /*_________________________________________________________________________
  58. **
  59. **            A C T I O N    R O U T I N E S
  60. */
  61.  
  62. /*    Character handling
  63. **    ------------------
  64. */
  65.  
  66. PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
  67. {
  68.   int rv;
  69.  
  70.   if (me->write_error)
  71.     return;
  72.  
  73.   /* Make sure argument to putc is in range 0-255, to avoid weirdness
  74.      with rv == -1 == EOF when it's not supposed to. */
  75.   rv = putc ((int)(unsigned char)c, me->fp);
  76.  
  77.   if (rv == EOF)
  78.     {
  79.       HTProgress ("Error writing to temporary file.");
  80.       me->write_error = 1;
  81.     }
  82. }
  83.  
  84.  
  85. /*    String handling
  86. **    ---------------
  87. **
  88. **    Strings must be smaller than this buffer size.
  89. */
  90. PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
  91. {
  92.   int rv;
  93.  
  94.   if (me->write_error)
  95.     return;
  96.  
  97.   rv = fputs(s, me->fp);
  98.   if (rv == EOF)
  99.     {
  100.       HTProgress ("Error writing to temporary file.");
  101.       me->write_error = 1;
  102.     }
  103. }
  104.  
  105.  
  106. /*    Buffer write.  Buffers can (and should!) be big.
  107. **    ------------
  108. */
  109. PRIVATE void HTFWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
  110. {
  111.   int rv;
  112.  
  113.   if (me->write_error)
  114.     return;
  115.  
  116.   rv = fwrite(s, 1, l, me->fp);
  117.   if (rv != l)
  118.     {
  119.       HTProgress ("Error writing to temporary file.");
  120.       me->write_error = 1;
  121.     }
  122. }
  123.  
  124.  
  125. /*    Free an HTML object
  126. **    -------------------
  127. **
  128. **    Note that the SGML parsing context is freed, but the created
  129. **    object is not,
  130. **    as it takes on an existence of its own unless explicitly freed.
  131. */
  132. PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
  133. {
  134.   HText *text;
  135.  
  136.   /* I dunno if this is necessary... */
  137.   if (me->interrupted)
  138.     {
  139.       free (me->fnam);
  140.       free (me);
  141.       return;
  142.     }
  143.  
  144.   if (me->write_error)
  145.     {
  146.       char *cmd = (char *)malloc ((strlen (me->fnam) + 32));
  147. #ifdef _AMIGA
  148.       sprintf (cmd, "run >NIL: <NIL: delete %s", me->fnam);
  149. #else
  150.       sprintf (cmd, "/bin/rm -f %s &", me->fnam);
  151. #endif
  152.       system (cmd);
  153.       free (cmd);
  154.  
  155.       HTProgress ("Insufficient temporary disk space; could not transfer data.");
  156.  
  157.       free (me->fnam);
  158.       free (me);
  159.       return;
  160.     }
  161.  
  162.   fflush (me->fp);
  163.   fclose (me->fp);
  164.  
  165.   /* We do want to be able to handle compressed inlined images,
  166.      but we don't want transparent uncompression to take place
  167.      in binary transfer mode. */
  168.   if (!binary_transfer && me->compressed != COMPRESSED_NOT)
  169.     {
  170.       if (TRACE)
  171.     fprintf (stderr, "[HTFWriter] Hi there; compressed is %d, fnam is '%s'\n",
  172.          me->compressed, me->fnam);
  173.       HTCompressedFileToFile (me->fnam, me->compressed);
  174.     }
  175.  
  176.   if (force_dump_to_file)
  177.     {
  178.       if (!binary_transfer)
  179.     goto done;
  180.     }
  181.  
  182.   /* Now, me->end_command can either be something starting with
  183.      "<mosaic-internal-reference" or it can be a real command.
  184.      Deal with appropriately. */
  185.   if (me->end_command)
  186.     {
  187.       /* Check for forced dump condition.  The left paren comes
  188.      from the construction of me->end_command as a compound shell
  189.      command below. */
  190.       if (strstr (me->end_command, "mosaic-internal-dump"))
  191.     {
  192.       rename_binary_file (me->fnam);
  193.     }
  194.       else if (!strstr (me->end_command, "mosaic-internal-reference"))
  195.     {
  196.       HTProgress("Spawning external viewer.");
  197. #ifdef _AMIGA
  198. #if 1
  199.       {
  200.           /* MBS 28 Jan 95
  201.           ** this is somewhat cleaner
  202.           */
  203.           char
  204.             *semi = me->end_command;
  205.           BPTR
  206.             inp = Open ("NIL:", MODE_NEWFILE);
  207.           LONG
  208.             rslt;
  209.  
  210.           if (TRACE)
  211.           {
  212.             fprintf (stderr, "About to SystemTags(%s)\n", semi);
  213.           }
  214.  
  215.           while (*semi)
  216.           {
  217.             if (*semi == ';')
  218.                 *semi = '\n';
  219.             ++semi;
  220.           }
  221.  
  222.           rslt = SystemTags (me->end_command,
  223.                 SYS_Input,       inp,
  224.                 SYS_Output,    0,
  225.                 SYS_Asynch,    1,
  226.                 SYS_UserShell, 1,
  227.                 NP_StackSize,  20000,
  228.                 TAG_DONE);
  229.  
  230.           if (rslt == -1)
  231.           {
  232.             /* System() failed, we must clean up */
  233.             Close (inp);
  234.           }
  235.           if (TRACE)
  236.           {
  237.             fprintf (stderr, "SystemTags() result %ld\n", rslt);
  238.           }
  239.  
  240.       }
  241. #else
  242.       { /*MJW 17 Oct 1993  -- can't put multiple commands on a line
  243.           if we wish to RUN them,
  244.           so made temporary script instead -
  245.           updated Nov 7 1993 removed free endcommand
  246.           updated October 4 1994 to fix overzealous deletion I hope.*/
  247.         static char AMcommandprefix[]="RUN >NIL: <NIL: EXECUTE ";
  248.         char *AMcommand=
  249.          (char *)malloc(strlen(AMcommandprefix)+16+L_tmpnam);
  250.         char *AMcomfile=AMcommand+strlen(AMcommandprefix);
  251.         FILE *AMtmpfile;
  252.         sprintf(AMcommand,AMcommandprefix);
  253.         tmpnam (AMcomfile);
  254.         if (TRACE) fprintf(stderr,"Amiga command string is %s (on %s)\n",
  255.             AMcommand,AMcomfile );
  256.         if ((FILE *)NULL ==(AMtmpfile = fopen(AMcomfile,"w"))){
  257.           HTAlert("Can't open script temporary file!");
  258.           free(AMcommand);
  259.         } else {
  260.           /* break the command apart at semicolons */
  261.           static char AMdelprefix[]="run >NIL: <NIL: delete ";
  262.           char *semi;
  263.           char *AMdelcommand=
  264.         (char *)malloc(strlen(AMdelprefix)+16+L_tmpnam);
  265.           sprintf(AMdelcommand,"%s %s",AMdelprefix,AMcomfile);
  266.           for (semi=me->end_command; *semi; semi++)
  267.         if (*semi == ';') *semi='\n';
  268.           /* Then stick it in a command file */
  269.           fprintf(AMtmpfile,".bra {\n");
  270.           fprintf(AMtmpfile,".ket }\n\n");
  271.           fprintf(AMtmpfile,"%s\n\n",me->end_command);
  272.           if (TRACE) {
  273.         printf(".bra {\n");
  274.         printf(".ket }\n\n");
  275.         printf("%s\n\n",me->end_command);
  276.           }
  277.           /* I don't know whether the file *can* delete itself
  278.          but not doing so is better than it
  279.          deleting itself before it runs  --- seems to work */
  280.           fprintf(AMtmpfile,"%s \n",AMdelcommand);
  281.           if (TRACE) printf("%s \n",AMdelcommand), fflush(stdout);
  282.           fclose(AMtmpfile);
  283.           if (TRACE) printf("system(AMcommand=%s);\n",AMcommand),
  284.             fflush(stdout);
  285.  
  286.           system(AMcommand);
  287.           free(AMcommand);
  288.           free(AMdelcommand);
  289.         }
  290.       }
  291. #endif
  292. #else          /* Not an amiga */
  293.       system (me->end_command);
  294. #endif          /* ! _AMIGA */
  295.     }
  296.       else
  297.     {
  298.       /* Internal reference, aka HDF file.    Just close output file. */
  299.     }
  300.     }
  301.   else
  302.     {
  303.       /* No me->end_command; just close the file. */
  304.     }
  305.  
  306.   /* Construct dummy HText thingie so Mosaic knows
  307.      not to try to access this "document". */
  308.   text = HText_new ();
  309.   HText_beginAppend (text);
  310.   /* If it's a real internal reference, tell Mosaic. */
  311.   if (me->end_command)
  312.     {
  313.       if (strstr (me->end_command, "mosaic-internal-reference"))
  314.     {
  315.       HText_appendText (text, me->end_command);
  316.     }
  317.       else
  318.     {
  319.       HText_appendText (text, "<mosaic-access-override>\n");
  320.     }
  321.       free (me->end_command);
  322.     }
  323.   else
  324.     {
  325.       /* No me->end_command; just override the access. */
  326.       HText_appendText (text, "<mosaic-access-override>\n");
  327.     }
  328.   HText_endAppend (text);
  329.  
  330.  done:
  331.   if (binary_transfer)
  332.     rename_binary_file (me->fnam);
  333.  
  334.  really_done:
  335.   free (me->fnam);
  336.   free (me);
  337.  
  338.   return;
  339. }
  340.  
  341. /*    End writing
  342. */
  343.  
  344. PRIVATE void HTFWriter_end_document ARGS1(HTStream *, me)
  345. {
  346.   if (me->interrupted || me->write_error)
  347.     return;
  348.  
  349.   fflush(me->fp);
  350. }
  351.  
  352. PRIVATE void HTFWriter_handle_interrupt ARGS1(HTStream *, me)
  353. {
  354.   char *cmd;
  355.  
  356.   if (me->write_error)
  357.     goto outtahere;
  358.  
  359.   /* Close the file, then kill it. */
  360.   fclose (me->fp);
  361.  
  362.   cmd = (char *)malloc ((strlen (me->fnam) + 32) * sizeof (char));
  363. #ifdef _AMIGA
  364.       sprintf (cmd, "run >NIL: <NIL: delete %s", me->fnam);
  365. #else
  366.       sprintf (cmd, "/bin/rm -f %s &", me->fnam);
  367. #endif
  368.   system (cmd);
  369.   free (cmd);
  370.  
  371.   if (TRACE)
  372.     fprintf (stderr, "*** HTFWriter interrupted; killed '%s'\n", me->fnam);
  373.  
  374.  outtahere:
  375.   me->interrupted = 1;
  376.  
  377.   return;
  378. }
  379.  
  380.  
  381. /*    Structured Object Class
  382. **    -----------------------
  383. */
  384. PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
  385. {
  386.     "FileWriter",
  387.     HTFWriter_free,
  388.     HTFWriter_end_document,
  389.     HTFWriter_put_character,    HTFWriter_put_string,
  390.     HTFWriter_write,
  391.     HTFWriter_handle_interrupt
  392. };
  393.  
  394.  
  395. /*    Take action using a system command
  396. **    ----------------------------------
  397. **
  398. **    Creates temporary file, writes to it, executes system command
  399. **    on end-document.  The suffix of the temp file can be given
  400. **    in case the application is fussy, or so that a generic opener can
  401. **    be used.
  402. **
  403. **    WARNING: If force_dump_to_file is high, pres may be NULL
  404. **    (as we may get called directly from HTStreamStack).
  405. */
  406. PUBLIC HTStream* HTSaveAndExecute ARGS5(
  407.     HTPresentation *,    pres,
  408.     HTParentAnchor *,    anchor, /* Not used */
  409.     HTStream *,        sink,
  410.     HTFormat,        format_in,
  411.     int,            compressed)    /* Not used */
  412. {
  413.   char *command;
  414.   CONST char * suffix;
  415.  
  416.   HTStream* me;
  417.  
  418.   me = (HTStream*)malloc(sizeof(*me));
  419.   me->isa = &HTFWriter;
  420.   me->interrupted = 0;
  421.   me->write_error = 0;
  422.   me->fnam = NULL;
  423.   me->end_command = NULL;
  424.   me->compressed = compressed;
  425.  
  426.   if (TRACE)
  427.     fprintf (stderr, "[HTSaveAndExecute] me->compressed is '%d'\n",
  428.          me->compressed);
  429.  
  430.   /* Save the file under a suitably suffixed name */
  431.  
  432.   if (!force_dump_to_file)
  433.     {
  434.       extern char *mo_tmpnam (void);
  435.  
  436.       suffix = HTFileSuffix(pres->rep);
  437.  
  438.       me->fnam = mo_tmpnam();
  439.       if (suffix)
  440.     {
  441.       char *freeme = me->fnam;
  442.  
  443.       me->fnam = (char *)malloc (strlen (me->fnam) + strlen (suffix) + 8);
  444.       strcpy(me->fnam, freeme);
  445.       strcat(me->fnam, suffix);
  446.       free (freeme);
  447.     }
  448.     }
  449.   else
  450.     {
  451.       me->fnam = strdup (force_dump_filename);
  452.     }
  453.  
  454.   me->fp = fopen (me->fnam, "w");
  455.   if (!me->fp)
  456.     {
  457.       HTProgress("Can't open temporary file -- serious problem.");
  458.       me->write_error = 1;
  459.       return me;
  460.     }
  461.  
  462.   /* If force_dump_to_file is high, we're done here. */
  463.   if (!force_dump_to_file)
  464.     {
  465.       if (!strstr (pres->command, "mosaic-internal-reference"))
  466.     {
  467.       /* If there's a "%s" in the command, or if the command
  468.          is magic... */
  469.       if (TRACE)
  470.         fprintf (stderr, "HTFWriter: pres->command is '%s'\n",
  471.              pres->command);
  472.       if (strstr (pres->command, "%s") ||
  473.           strstr (pres->command, "mosaic-internal"))
  474.         {
  475.           /* Make command to process file */
  476.           command = (char *)malloc
  477.         ((strlen (pres->command) + 10 + 3*strlen(me->fnam)) *
  478.          sizeof (char));
  479.  
  480.           /* Cute.    pres->command will be something like "xv %s"; me->fnam
  481.          gets filled in as many times as appropriate.  */
  482.           sprintf (command, pres->command, me->fnam, me->fnam, me->fnam);
  483. #ifdef _AMIGA
  484.        { /* For the amiga only, if @ appears in the string,
  485.         terminate the string there, and append the screen name
  486.            to the command, so the program will run on
  487.            the screen amosaic is running on */
  488.          /* This hack may be obsolete! as of Mosaic 2.0 */
  489.         char  *scrptr = (char *)strchr(command,'@');
  490.         extern char *gui_whichscreen(void);
  491.         if (scrptr != NULL) {
  492.           *scrptr=(char)0;
  493.           scrptr = gui_whichscreen();
  494.           me->end_command =
  495.         (char *)malloc((strlen (command)+32+strlen(me->fnam)+strlen(scrptr))
  496.                    * sizeof (char));
  497.           sprintf (me->end_command, "%s PUBSCREEN=\"%s\"\n delete %s ",
  498.                command, scrptr, me->fnam);
  499.         } else {
  500.           me->end_command =
  501.         (char *)malloc ((strlen (command) + 32 + strlen(me->fnam))
  502.                 * sizeof (char));
  503.           sprintf (me->end_command, "%s \n delete %s ",
  504.                command, me->fnam);
  505.         }
  506.       }
  507.  
  508. #else /* NOT an AMIGA */
  509.  
  510.           me->end_command = (char *)malloc
  511.         ((strlen (command) + 32 + strlen(me->fnam)) * sizeof (char));
  512.           sprintf (me->end_command, "(%s ; /bin/rm -f %s) &",
  513.                command, me->fnam);
  514. #endif
  515.           free (command);
  516.         }
  517.       else
  518.         {
  519.           /* Make command to process file -- but we have to cat
  520.          to the viewer's stdin. */
  521.         #ifdef _AMIGA
  522.           {
  523.         fprintf(stderr," Please send email to witbrock@cs.cmu.edu\n"
  524.             "telling him that you passed through the unsupported\n"
  525.             "pipe code and which URL it happened on. "
  526.             " say '((cat %s | %s); /bin/rm -f %s) &'"
  527.             "Also say:\n"
  528.             "\t file %s:%s line %d compiled %s %s\n",
  529.             me->fnam, pres->command, me->fnam,
  530.             __FILE__,__FUNC__,__LINE__,__DATE__,__TIME__);
  531.         fflush(stderr);
  532.           }
  533.  
  534.         #else /* NOT an AMIGA */
  535.           me->end_command = (char *)malloc
  536.         ((strlen (pres->command) + 64 + (2 * strlen(me->fnam))) *
  537.          sizeof (char));
  538.           sprintf (me->end_command, "((cat %s | %s); /bin/rm -f %s) &",
  539.                me->fnam, pres->command, me->fnam);
  540.         #endif
  541.         }
  542.     }
  543.       else
  544.     {
  545.       /* Overload me->end_command to be what we should write out as text
  546.          to communicate back to client code. */
  547.       me->end_command = (char *)malloc
  548.         (strlen ("mosaic-internal-reference") + strlen (me->fnam) + 32);
  549.       sprintf (me->end_command, "<%s \"%s\">\n", "mosaic-internal-reference", me->fnam);
  550.     }
  551.     }
  552.  
  553.   return me;
  554. }
  555.